<?php
/**
 *	KLF Framework
 *
 *	Written by Kristian Oye <kristianoye@gmail.com> on Nov 19, 2011
 *	Copyright (C) 2010-2011
 */
namespace KLF\System\Cache
{
	use KLF\System\Cache\KCache;
	use KLF\System\Cache\ICache;
	use KLF\System\Cache\ICacheable;
	use KLF\System\Errors\KFeatureException;
	use KLF\System\Errors\KArgumentException;
	use KLF\System\Errors\KConnectionException;
	
	/**
	 *  Class KMemcache extends KCache
	 *
	 *  Framework implementation/wrapper for Memcache
	 *
	 *  @package KLF\System\Cache\Memcache
	 *  @access public
	 *  @author Kristian Oye <kristianoye@gmail.com>
	 *  @since 0.1
	 *  
	 *  @see KMemcache::SetValue()
	 *  @see KMemcache::GetValues();
	 *  
	 *  @property int DefaultFlags
	 *  @property string Hostname
	 *  @property bool Initialized
	 *  @property \Memcache Memcache
	 *
	 *  @method KMemcache NewInstance
	 */
	class KMemcache extends KCache implements ICache
	{
		/**
		 * The default compression flags.
		 * 
		 * @var int $_propDefaultFlags
		 */
		protected $_propDefaultFlags;
		
		/**
		 * The hostname of the cache server.
		 * 
		 * @var string $_rpropHostname
		 */
		protected $_rpropHostname;
		
		/**
		 * The underlying Memcache object.
		 * 
		 * @var \Memcache $_rpropMemcache
		 */
		protected $_rpropMemcache;
		
		/**
		 * Constructs a new KMemcache object.
		 * 
		 * @param string $hostname The hostname of the server.
		 * @param integer $port The TCP port the memcached server is located on.
		 * @param unknown_type $timeout The number of seconds to wait for a connection (default of 1).
		 */
		public function __construct($hostname='localhost', $port=11211, $timeout=1, $defaultFlags = 0)
		{
			if (!extension_loaded('memcache')) {
				throw new KFeatureException('memcache');
			}
			$this->_rpropHostname = $hostname;
			$this->_propDefaultFlags = $defaultFlags;
			$this->_rpropMemcache = new \Memcache();
			
			if (!$this->_rpropMemcache->connect($hostname, $port, $timeout))
			{
				throw new KConnectionException($hostname,$port,'TCP','memcache','connection refused');
			}
		}
		
		/**
		 * Adds a new server to the memcache pool.
		 * 
		 * @param string $hostname The memcached server name.
		 * @param integer $port The port on which the memcached is located.
		 * @param boolean $persist True if the server should persist.
		 * @param integer $weight The weight given to the new server.  Determines how likely it is to be used.
		 * @param integer $timeout The amount of time before the server times out (defaults to 1s).
		 * @param integer $retryInterval The number of seconds to wait between connection attempts.
		 * @param boolean $status TRUE if online, FALSE if offline (remains in the pool, however).
		 * @param callable $onFailure The callback should the server fail.
		 * 
		 * @return KMemcache Returns a reference to the memcache object itself.
		 */
		public function AddServer($hostname, $port, $persist=TRUE, $weight=0, $timeout=1, $retryInterval=15, $status=TRUE, $onFailure = NULL)
		{
			$this->_rpropMemcache->addServer(
				$hostname, 
				$port, 
				$persist, 
				$weight, 
				$timeout, 
				$retryInterval, 
				$status, 
				$onFailure);
			
			return $this;
		}
		
		/**
		 * Adds a value to the cache.
		 * 
		 * @param string $key The key associated with the value.
		 * @param mixed $val
		 * @param integer $expires
		 * @param integer $flag
		 * 
		 * @return boolean True if successfully added, false if it failed.
		 */
		public function AddValue($key, $val, $expires=0, $flag = NULL)
		{
			return $this->_rpropMemcache->add($key, $val, $flag, $expires);
		}
		
		/**
		 * Deletes values from the cache by using one or more cache keys.
		 *
		 * @author: Kristian Oye <kristianoye@gmail.com>
		 * @since 0.1
		 * @return integer Returns the number of deleted keys.
		*/
		public function DeleteValues()
		{
			if (count($args) == 0) {
				throw new KArgumentException("Insufficient arguments to DeleteValues()");
			}
			foreach($args as $keyName) {
				$this->_rpropMemcache->delete($keyName);
			}
			return $this;
		}
		
		/**
		 * Clears all the values out of the memcache.
		 * 
		 * @see KLF\System\Cache.ICache::Flush()
		 */
		public function Flush()
		{
			$this->_rpropMemcache->flush();
			
			return $this;
		}
		
		/**
		 * Returns a single value from the cache.
		 * 
		 * @param string $key
		 * @see KLF\System\Cache.ICache::GetValue()
		 * @return mixed
		 */
		public function GetValue($key)
		{
			return $this->_rpropMemcache->get($key);
		}
		
		/**
		 * Returns a set of one or more values from the cache.
		 * 
		 * @see KLF\System\Cache.ICache::GetValues()
		 */
		public function GetValues()
		{
			$args = func_get_args();
			
			if (count($args) == 0) {
				throw new KArgumentException("Insufficient arguments to GetValues()");
			}
			return $this->_rpropMemcache->get($args);
		}
		
		/**
		* Initialize the fake cache object.
		 *
		* @see KLF\System\Cache.ICache::Initialize()
		*/
		public function Initialize()
		{
		}
		
		/**
		 * Add or update a value in the cache.
		 * 
		 * @param $key The key associated with the value and used to retrieve it.
		 * @param $val The value to store in the cache.
		 * @param $expires The maximum time the value should live in the cache.
		 * 
		 * @see KLF\System\Cache.ICache::SetValue()
		 */
		public function SetValue($key, $val, $expires = 0)
		{
			$this->_rpropMemcache->set($key, $val, $this->_propDefaultFlags, $expires);
			
			return $this;
		}
	}
}
